package com.lsy.poi.sheet;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;

import com.lsy.poi.Parser;
import com.lsy.poi.PluggableFileParser;
import com.lsy.poi.cell.CellParser;
import com.lsy.poi.row.RowParser;
import com.lsy.poi.row.indexer.RowIndexer;
import com.lsy.poi.sheet.validator.SheetValidator;

public class SheetParser extends Parser {
	
	private static Logger logger = Logger.getLogger(SheetParser.class);
	
	private String[] sheetNames;//多个 sheet 页，可以使用 同一组 RowParser 去进行解析 
	
	/**
	 * sheet 和 rowParsers、validators 之间是 "多对一" 的 关系，
	 * 即 "多个sheet" 可以使用 "一组RowParser、一组SheetValidator" 进行解析、验证
	 */
	private XSSFSheet[]			sheets;
	private RowParser[]			rowParsers;
	private SheetValidator[]	validators;
	
	
	/** 默认的 验证器列表：空，即 不做任何验证  */
	private final static SheetValidator[] DEFAULT_VALIDATORS = new SheetValidator[]{};
	
	@Override
	public void spreadErrorHook(List<String> errors) {
		for (RowParser rowParser : rowParsers) {
			rowParser.spreadErrorHook(errors);
		}
		
		for (SheetValidator sheetValidator : validators) {
			sheetValidator.setErrors(errors);
		}
	}
	
	/**
	 * 构造器
	 */
	public SheetParser(String[] sheetNames, RowParser[] rowParsers, SheetValidator[] validators) {
		super();
		this.sheetNames = sheetNames;
		this.rowParsers = rowParsers;
		this.validators = validators;
	}
	public SheetParser(String[] sheetNames, RowParser[] rowParsers) {
		this(sheetNames, rowParsers, DEFAULT_VALIDATORS);
	}
	

	/**
	 * 核心方法
	 */
	public void parse() throws Exception {
		for (XSSFSheet sheet : sheets) {
			
//			for (RowParser rowParser : rowParsers) {
//				//1、构建 XSSFRow[] rows
//				int beginIndex = rowParser.getBeginIndex();
//				int endIndex = rowParser.getEndIndex();
//				
//				XSSFRow[] rows = new XSSFRow[endIndex-beginIndex+1];
//				
//				for(int i=beginIndex; i<endIndex+1; i++) {
//					int index = i-beginIndex;
//					rows[index] = sheet.getRow(i);
//				}
//				
//				//2、将 rows 交给  rowParser
//				rowParser.setRows(rows);
//				
//				//3、解析 rowParser 中的  XSSFRow[] rows
//				rowParser.parse();
//				
//			}
			
			
			for (RowParser rowParser : rowParsers) {
				boolean started = false;
				
				List<XSSFRow> rowList = new ArrayList<>(); 
				
				RowIndexer rowIndexer = rowParser.getRowIndexer();
				
				while(true) {
					int i = rowIndexer.getIndex();
					
					logger.debug("***" + i);
					/** 避免 无限循环的 保护熔断 	 */
					if(i< sheet.getFirstRowNum()) continue;
					if(i> sheet.getLastRowNum()) break; //getLastRowNum() 是最后一个 "有值行" 的 行号（从 0 开始数）
					
					XSSFRow row = sheet.getRow(i);
					
					if(row == null) {
						row =sheet.createRow(i);
						logger.debug("%%%%%%%%%%%%%%%%");
						logger.debug(row.getFirstCellNum() + " ^^^ " + row.getLastCellNum());
						//遍历 cell
						for (int ii = 0; ii < row.getLastCellNum(); ii++) {
							System.out.print(row.getCell(ii) + ", ");
						}
						logger.debug("");
						logger.debug("@@@@@@@@@@@@@@@@");
						
					}
					
					if(!started) {
						if(rowIndexer.triggerBeginning(row)) {//开头
							logger.debug("开头啦~~~，将这个 row 加入 list");
							
							/***/
							logger.debug("====@@##@@##======> " + i);
							/* if(row==null) break; */  //拿到 row 之后，不应当做 任何 操作、判断，要 原封原样 交给 indexer
//							logger.debug("SSSS => 0: " + row.getCell(0));
//							logger.debug("SSSS => " + row.getFirstCellNum() + ": " + row.getCell(row.getFirstCellNum()));
//							logger.debug("SSSS => " + (row.getLastCellNum()-1) + ": " + row.getCell(row.getLastCellNum()-1));
							/***/
							
							rowList.add(row);
							rowParser.setBeginIndex(i);
							
							started = true;
							
							
							rowIndexer.incrementIndex();
							continue;
							
						} else {//开不了头
							logger.debug("诶111，还是 开不了头");
							
							rowIndexer.incrementIndex();
							continue;
						}
					}
					
					if(!rowIndexer.triggerEnding(row)) {//结不了尾，仍旧需要 将这个 cell 加入 list
						logger.debug("结不了尾，仍旧需要 将这个 row 加入 list");
						
						/***/
						logger.debug("====@@##@@##======> " + i);
						/* if(row==null) break; */  //拿到 row 之后，不应当做 任何 操作、判断，要 原封原样 交给 indexer
						
//						logger.debug("SSSS => 0: " + row.getCell(0));
//						logger.debug("SSSS => " + row.getFirstCellNum() + ": " + row.getCell(row.getFirstCellNum()));
//						logger.debug("SSSS => " + (row.getLastCellNum()-1) + ": " + row.getCell(row.getLastCellNum()-1));
						
						/***/
						
						rowList.add(row);
						rowParser.setEndIndex(i);
						
						rowIndexer.incrementIndex();
						continue;
						
					}else {//结尾了，跳出 无限循环，不再 拿 cell 了
						logger.debug("结尾啦~~~~");
						started = false;
						
						break;
					}
				}
				
				XSSFRow[] rows = (XSSFRow[]) rowList.toArray(new XSSFRow[0]);
				logger.debug("收集的 行数：" + rows.length);
				
				//2、将 rows 交给  rowParser
				rowParser.setRows(rows);
				
				//3、解析 rowParser 中的  XSSFRow[] rows
				rowParser.parse();
			}
			
			//页验证器
			for (SheetValidator sheetValidator : validators) {
				sheetValidator.validate(sheet);
			}
			
			//TODO: 多个行 享用一组 CellParser，但是 CellIndexer 是不能 跨行的，要把 CellIndexer 的 恢复初始情况，即 reset
			//解决：方法1：深拷贝？  方法2：在 Indexer 中设计一个 reset 方法 
			
			//reset 之后，才能为 新的 行服务
			//注意：有时 cellParsers 的 indexer 会共享，也就是说 
			//多次 cellParser.getCellIndexer().resetIndex(); 可能 恢复的 是 同一个对象
			//不然会发生 无限循环:
			//XSSFRow row = sheet.getRow(i); 由于 i 没有被 reset，所以 取到的 row 为 null
			//导致 indexer.triggerBeginning(row) 总是 返回 false
			for (RowParser rowParser : rowParsers) {
				rowParser.getRowIndexer().resetIndex();
			}
			
		}
	}

	
	public String[] getSheetNames() {
		return sheetNames;
	}

	public void setSheetNames(String[] sheetNames) {
		this.sheetNames = sheetNames;
	}

	public XSSFSheet[] getSheets() {
		return sheets;
	}

	public void setSheets(XSSFSheet[] sheets) {
		this.sheets = sheets;
	}

	public RowParser[] getRowParsers() {
		return rowParsers;
	}

	public void setRowParsers(RowParser[] rowParsers) {
		this.rowParsers = rowParsers;
	}

	public SheetValidator[] getValidators() {
		return validators;
	}

	public void setValidators(SheetValidator[] validators) {
		this.validators = validators;
	}
	
	
}
